package org.onionframework.persistence.model.support;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.usertype.ParameterizedType;
import org.hibernate.usertype.UserType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * 扩展属性ExtendProperties对应的Hibernate类型
 * 
 * @author allan
 */

public class XMLType implements UserType,ParameterizedType {

	private Logger logger = LoggerFactory.getLogger(XMLType.class);
	private int[] sqlTypes = new int[]{Types.CLOB};
	private XMLMapConverter converter;
	
	public XMLType(){
		try {
			converter = (XMLMapConverter) Class.forName("org.onionframework.persistence.model.support.DefaultXMLMapConverter").newInstance();
		} catch (Exception e) {
			logger.info("XMLMapConverter找不到，你必须在使用的时候指定");
		}
	}
	
	public Object assemble(Serializable cached, Object owner)
			throws HibernateException {
		return cached;
	}

	@SuppressWarnings("unchecked")
	public Object deepCopy(Object arg0) throws HibernateException {
		if(arg0 == null)
			return null;
		
		Map<String,String> map = (Map<String,String>)arg0;
		Map<String,String> newMap = new HashMap<String,String>();
		newMap.putAll(map);
		return newMap;
	}

	@SuppressWarnings("unchecked")
	public Serializable disassemble(Object obj) throws HibernateException {
		return (HashMap<String,String>)obj;
	}

	public boolean equals(Object arg0, Object arg1) throws HibernateException {
		if(arg0 == arg1)
			return true;
		else if(arg0 == null || arg1 == null)
			return false;
		else
			return arg0.equals(arg1);
	}

	public int hashCode(Object arg0) throws HibernateException {
		return arg0.hashCode();
	}

	public boolean isMutable() {
		return false;
	}

	public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
			throws HibernateException, SQLException {
		
		String storeString = rs.getString(names[0]);
		
		return this.converter.toMap(storeString);
	}

	@SuppressWarnings("unchecked")
	public void nullSafeSet(PreparedStatement ps, Object obj, int index)
			throws HibernateException, SQLException {
		if(obj == null)
			ps.setNull(index, Types.VARCHAR);
		else{
			Map<String,Object> map = (Map<String,Object>)obj;
			ps.setString(index, this.converter.toString(map));
		}
	}

	public Object replace(Object arg0, Object arg1, Object arg2)
			throws HibernateException {
		return arg0;
	}

	@SuppressWarnings("unchecked")
	public Class returnedClass() {
		return Map.class;
	}

	public int[] sqlTypes() {
		return this.sqlTypes;
	}

	@Override
	public void setParameterValues(Properties params) {
		if(params != null && params.containsKey("converter"))
			try {
				this.converter = (XMLMapConverter)Class.forName(params.getProperty("converter")).newInstance();
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
	}

	@Override
	public Object nullSafeGet(ResultSet arg0, String[] arg1,
			SessionImplementor arg2, Object arg3) throws HibernateException,
			SQLException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void nullSafeSet(PreparedStatement arg0, Object arg1, int arg2,
			SessionImplementor arg3) throws HibernateException, SQLException {
		// TODO Auto-generated method stub
		
	}

}
